"""" 
Copyright 2009 Texas A&M University
 
Licensed under the Apache License, Version 2.0 (the "License"); you may not use 
this file except in compliance with the License. You may obtain a copy of the 
License at

http://www.apache.org/licenses/LICENSE-2.0
  
Unless required by applicable law or agreed to in writing, software distributed 
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
CONDITIONS OF ANY KIND, either express or implied. See the License for the 
specific language governing permissions and limitations under the License.
"""

from logging import getLogger
from re import compile

from meercat.mapreduce.reducers.utils import setReduction



__all__ = ['ClassFromCallNumber','SubclassFromCallNumber',]

log = getLogger('meercat.mapreduce.reducers.lccn')

_class_re = compile(r'^([A-Z]).*$')
_subclass_re = compile(r'^([A-Z]{1,3})(\d?\s?).*$')

def extractClass(value):
    match = _class_re.match(value)
    if match:
        log.debug('extractClass(%s) -> %s' % (str(value),match.group(1),))
        return match.group(1)
    log.debug('extractClass(%s) -> None' % (str(value)))
    return None

def extractSubclass(value):
    match = _subclass_re.match(value)
    if match:
        log.debug('extractSubclass(%s) -> %s' % (str(value),match.group(1),))
        return match.group(1)
    log.debug('extractSubclass(%s) -> None' % (str(value)))
    return None

LCCNMap = {
    'A': 'General Works',
    'B': 'Philosphy, Psychology, Religion',
    'C': 'Auxiliary Sciences of History',
    'D': 'General and Old World History',
    'E': 'History of America',
    'F': 'History of the United States and British, Dutch, French, and Latin America',
    'G': 'Geography, Anthropolgy, and Recreation',
    'H': 'Social Sciences',
    'J': 'Political Science',
    'K': 'Law',
    'L': 'Education',
    'M': 'Music',
    'N': 'Fine Arts',
    'P': 'Language and Literature',
    'Q': 'Science',
    'R': 'Medicine',
    'S': 'Agriculture',
    'T': 'Technology',
    'U': 'Military Science',
    'V': 'Naval Science',
    'Z': 'Bibliography, Library Science, and General Information Resources'}

LCCNsubclassMap = {
    'AC': 'Collections. Series. Collected works',
    'AE': 'Encyclopedias',
    'AG': 'Dictionaries and other general reference works',
    'AI': 'Indexes',
    'AM': 'Museums. Collectors and collecting',
    'AN': 'Newspapers',
    'AP': 'Periodicals',
    'AS': 'Academies and learned societies',
    'AY': 'Yearbooks. Almanacs. Directories',
    'AZ': 'History of scholarship and learning. The humanities',
    'B': 'Philosophy (General)',
    'BC': 'Logic',
    'BD': 'Speculative philosophy',
    'BF': 'Psychology',
    'BH': 'Aesthetics',
    'BJ': 'Ethics',
    'BL': 'Religions. Mythology. Rationalism',
    'BM': 'Judaism',
    'BP': 'Islam. Bahaism. Theosophy, etc.',
    'BQ': 'Buddhism',
    'BR': 'Christianity',
    'BS': 'The Bible',
    'BT': 'Doctrinal Theology',
    'BV': 'Practical Theology',
    'BX': 'Christian Denominations',
    'C': 'Auxiliary Sciences of History (General)',
    'CB': 'History of Civilization',
    'CC': 'Archaeology',
    'CD': 'Diplomatics. Archives. Seals',
    'CE': 'Technical Chronology. Calendar',
    'CJ': 'Numismatics',
    'CN': 'Inscriptions. Epigraphy',
    'CR': 'Heraldry',
    'CS': 'Genealogy',
    'CT': 'Biography',
    'D': 'History (General)',
    'DA': 'Great Britain',
    'DAW': 'Central Europe',
    'DB': 'Austria - Liechtenstein - Hungary - Czechoslovakia',
    'DC': 'France - Andorra - Monaco',
    'DD': 'Germany',
    'DE': 'Greco-Roman World',
    'DF': 'Greece',
    'DG': 'Italy - Malta',
    'DH': 'Low Countries - Benelux Countries',
    'DJ': 'Netherlands (Holland)',
    'DJK': 'Eastern Europe (General)',
    'DK': 'Russia. Soviet Union. Former Soviet Republics - Poland',
    'DL': 'Northern Europe. Scandinavia',
    'DP': 'Spain - Portugal',
    'DQ': 'Switzerland',
    'DR': 'Balkan Peninsula',
    'DS': 'Asia',
    'DT': 'Africa',
    'DU': 'Oceania (South Seas)',
    'DX': 'Gypsies',
    'E': 'History of America',
    'F': 'Local History of the United States and British, Dutch, French, and Latin America',
    'G': 'Geography (General). Atlases. Maps',
    'GA': 'Mathematical geography. Cartography',
    'GB': 'Physical geography',
    'GC': 'Oceanography',
    'GE': 'Environmental Sciences',
    'GF': 'Human ecology. Anthropogeography',
    'GN': 'Anthropology',
    'GR': 'Folklore',
    'GT': 'Manners and customs (General)',
    'GV': 'Recreation. Leisure',
    'H': 'Social sciences (General)',
    'HA': 'Statistics',
    'HB': 'Economic theory. Demography',
    'HC': 'Economic history and conditions',
    'HD': 'Industries. Land use. Labor',
    'HE': 'Transportation and communications',
    'HF': 'Commerce',
    'HG': 'Finance',
    'HJ': 'Public finance',
    'HM': 'Sociology (General)',
    'HN': 'Social history and conditions. Social problems. Social reform',
    'HQ': 'The family. Marriage. Women',
    'HS': 'Societies: secret, benevolent, etc.',
    'HT': 'Communities. Classes. Races',
    'HV': 'Social pathology. Social and public welfare. Criminology',
    'HX': 'Socialism. Communism. Anarchism',
    'J': 'General legislative and executive papers',
    'JA': 'Political science (General)',
    'JC': 'Political theory',
    'JF': 'Political institutions and public administration',
    'JJ': 'Political institutions and public administration (North America)',
    'JK': 'Political institutions and public administration (United States)',
    'JL': 'Political institutions and public administration (Canada, Latin America, etc.)',
    'JN': 'Political institutions and public administration (Europe)',
    'JQ': 'Political institutions and public administration (Asia, Africa, Australia, Pacific Area, etc.)',
    'JS': 'Local government. Municipal government',
    'JV': 'Colonies and colonization. Emigration and immigration. International migration',
    'JX': 'International law',
    'JZ': 'International relations',
    'K': 'Law in general. Comparative and uniform law. Jurisprudence',
    'KB': 'Religious law in general. Comparative religious law. Jurisprudence',
    'KBM': 'Jewish law',
    'KBP': 'Islamic law',
    'KBR': 'History of canon law',
    'KBU': 'Law of the Roman Catholic Church. The Holy See',
    'KD': 'United Kingdom and Ireland',
    'KDA': 'United Kingdom and Ireland',
    'KDB': 'United Kingdom and Ireland',
    'KDC': 'United Kingdom and Ireland',
    'KDD': 'United Kingdom and Ireland',
    'KDE': 'United Kingdom and Ireland',
    'KDF': 'United Kingdom and Ireland',
    'KDG': 'United Kingdom and Ireland',
    'KDH': 'United Kingdom and Ireland',
    'KDI': 'United Kingdom and Ireland',
    'KDJ': 'United Kingdom and Ireland',
    'KDK': 'United Kingdom and Ireland',
    'KDZ': 'America. North America',
    'KE': 'Canada',
    'KF': 'United States',
    'KG': 'Latin America - Mexico and Central America - West Indies. Caribbean area',
    'KH': 'South America',
    'KJ': 'Europe',
    'KK': 'Europe',
    'KL': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KM': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KN': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KO': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KP': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KQ': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KR': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KS': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KT': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KU': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KV': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KW': 'Asia and Eurasia, Africa, Pacific Area, and Antarctica',
    'KZ': 'Law of nations',
    'L': 'Education (General)',
    'LA': 'History of education',
    'LB': 'Theory and practice of education',
    'LC': 'Special aspects of education',
    'LD': 'Individual institutions - United States',
    'LE': 'Individual institutions - America (except United States)',
    'LF': 'Individual institutions - Europe',
    'LG': 'Individual institutions - Asia, Africa, Indian Ocean islands, Australia, New Zealand, Pacific islands',
    'LH': 'College and school magazines and papers',
    'LJ': 'Student fraternities and societies, United States',
    'LT': 'Textbooks',
    'M': 'Music',
    'ML': 'Literature on music',
    'MT': 'Instruction and study',
    'N': 'Visual arts',
    'NA': 'Architecture',
    'NB': 'Sculpture',
    'NC': 'Drawing. Design. Illustration',
    'ND': 'Painting',
    'NE': 'Print media',
    'NK': 'Decorative arts',
    'NX': 'Arts in general',
    'P': 'Philology. Linguistics',
    'PA': 'Greek language and literature. Latin language and literature',
    'PB': 'Modern languages. Celtic languages',
    'PC': 'Romanic languages',
    'PD': 'Germanic languages. Scandinavian languages',
    'PE': 'English language',
    'PF': 'West Germanic languages',
    'PG': 'Slavic languages and literatures. Baltic languages. Albanian language',
    'PH': 'Uralic languages. Basque language',
    'PJ': 'Oriental languages and literatures',
    'PK': 'Indo-Iranian languages and literatures',
    'PL': 'Languages and literatures of Eastern Asia, Africa, Oceania',
    'PM': 'Hyperborean, Indian, and artificial languages',
    'PN': 'Literature (General)',
    'PQ': 'French literature - Italian literature - Spanish literature - Portuguese literature',
    'PR': 'English literature',
    'PS': 'American literature',
    'PT': 'German literature - Dutch literature - Flemish literature since 1830 -Afrikaans literature - Scandinavian literature - Old Norse literature: Old Icelandic and Old Norwegian - Modern Icelandic literature - Faroese literature - Danish literature - Norwegian literature - Swedish literature',
    'PZ': 'Fiction and juvenile belles lettres',
    'Q': 'Science (General)',
    'QA': 'Mathematics',
    'QB': 'Astronomy',
    'QC': 'Physics',
    'QD': 'Chemistry',
    'QE': 'Geology',
    'QH': 'Natural history - Biology',
    'QK': 'Botany',
    'QL': 'Zoology',
    'QM': 'Human anatomy',
    'QP': 'Physiology',
    'QR': 'Microbiology',
    'R': 'Medicine (General)',
    'RA': 'Public aspects of medicine',
    'RB': 'Pathology',
    'RC': 'Internal medicine',
    'RD': 'Surgery',
    'RE': 'Ophthalmology',
    'RF': 'Otorhinolaryngology',
    'RG': 'Gynecology and obstetrics',
    'RJ': 'Pediatrics',
    'RK': 'Dentistry',
    'RL': 'Dermatology',
    'RM': 'Therapeutics. Pharmacology',
    'RS': 'Pharmacy and materia medica',
    'RT': 'Nursing',
    'RV': 'Botanic, Thomsonian, and eclectic medicine',
    'RX': 'Homeopathy',
    'RZ': 'Other systems of medicine',
    'S': 'Agriculture (General)',
    'SB': 'Plant culture',
    'SD': 'Forestry',
    'SF': 'Animal culture',
    'SH': 'Aquaculture. Fisheries. Angling',
    'SK': 'Hunting sports',
    'T': 'Technology (General)',
    'TA': 'Engineering (General). Civil engineering',
    'TC': 'Hydraulic engineering. Ocean engineering',
    'TD': 'Environmental technology. Sanitary engineering',
    'TE': 'Highway engineering. Roads and pavements',
    'TF': 'Railroad engineering and operation',
    'TG': 'Bridge engineering',
    'TH': 'Building construction',
    'TJ': 'Mechanical engineering and machinery',
    'TK': 'Electrical engineering. Electronics. Nuclear engineering',
    'TL': 'Motor vehicles. Aeronautics. Astronautics',
    'TN': 'Mining engineering. Metallurgy',
    'TP': 'Chemical technology',
    'TR': 'Photography',
    'TS': 'Manufactures',
    'TT': 'Handicrafts. Arts and crafts',
    'TX': 'Home economics',
    'U': 'Military science (General)',
    'UA': 'Armies: Organization, distribution, military situation',
    'UB': 'Military administration',
    'UC': 'Maintenance and transportation',
    'UD': 'Infantry',
    'UE': 'Cavalry. Armor',
    'UF': 'Artillery',
    'UG': 'Military engineering. Air forces',
    'UH': 'Other services',
    'V': 'Naval science (General)',
    'VA': 'Navies: Organization, distribution, naval situation',
    'VB': 'Naval administration',
    'VC': 'Naval maintenance',
    'VD': 'Naval seamen',
    'VE': 'Marines',
    'VF': 'Naval ordnance',
    'VG': 'Minor services of navies',
    'VK': 'Navigation. Merchant marine',
    'VM': 'Naval architecture. Shipbuilding. Marine engineering',
    'Z': 'Books (General). Writing. Paleography. Book industries and trade. Libraries. Bibliography',
    'ZA': 'Information resources (General)'}

class ClassFromCallNumber(object):
    def __init__(self,classMap=LCCNMap,valueExtractor=extractClass):
        assert callable(valueExtractor),u'Value extractor must be callable'
        assert isinstance(classMap,dict),u'Class mapping must be a dictionary'
        self.classMap = classMap
        self.valueExtractor = valueExtractor
    
    def __call__(self, values):
        log.debug('%s.(%s)' % (str(self), str(values),))
        return setReduction(filter(lambda x: x is not None,
                                   map(self.classMap.get,
                                       map(self.valueExtractor,setReduction(values)))))
    
class SubclassFromCallNumber(ClassFromCallNumber):
    def __init__(self,subclassMap=LCCNsubclassMap,valueExtractor=extractSubclass):
        super(SubclassFromCallNumber,self).__init__(subclassMap,valueExtractor)